package com.cq.hd.app.biz;

import com.cq.hd.common.constant.Constant;
import com.cq.hd.common.enums.ResponseEnums;
import com.cq.hd.common.enums.biz.*;
import com.cq.hd.common.response.Result;
import com.cq.hd.common.response.ResultGenerator;
import com.cq.hd.common.response.Throw;
import com.cq.hd.common.utils.LocalDateUtil;
import com.cq.hd.member.api.TbBusinessApi;
import com.cq.hd.member.api.TbSubsidyAmtBillApi;
import com.cq.hd.member.api.dto.SubsidyAmtBillDto;
import com.cq.hd.member.api.vo.*;
import com.cq.hd.order.api.TbOrderApi;
import com.cq.hd.order.api.TbOrderItemApi;
import com.cq.hd.order.api.TbOrderSettleBillApi;
import com.cq.hd.order.api.dto.OrderDto;
import com.cq.hd.order.api.dto.OrderItemDto;
import com.cq.hd.order.api.dto.OrderSettleBillDto;
import com.cq.hd.order.api.vo.OrderItemVo;
import com.cq.hd.order.api.vo.OrderSettleBillVo;
import com.cq.hd.order.api.vo.OrderVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.stream.Collectors;

@Component
@Slf4j
public class SubsidyBiz {

    @Autowired
    private TbBusinessApi businessApi;

    @Autowired
    private TbOrderApi orderApi;

    @Autowired
    private TbOrderItemApi orderItemApi;

    @Autowired
    private TbOrderSettleBillApi orderSettleBillApi;

    @Autowired
    private TbSubsidyAmtBillApi subsidyAmtBillApi;

    public BusinessSubsidyVo getSubsidyData(Long businessId, Long userId) {
        BusinessPageVo businessPageVo;
        if (businessId == null || businessId <= 0) {
            if (userId == null || userId <= 0) {
                Throw.isBusinessException(ResponseEnums.USER_ACCESS_DENIED);
            }

            // 根据userId查询商家id
            businessPageVo = businessApi.getByUserId(userId).unpack();
            if (businessPageVo == null) {
                // 如果不是商家，则返回空
                Throw.isBusinessException(ResponseEnums.BUSINESS_ACCESS_DENIED);
            }
        } else {
            businessPageVo = businessApi.getById(businessId).unpack();
        }

        BigDecimal subsidyAmt = businessPageVo.getSubsidyAmt();
        // 待充值=已结算待打款的补贴金额-补贴账户余额=已结算的订单的总补贴金额-当前补贴账户金额=已结算的订单的订单补贴金额+红包金额-当前补贴账户金额
        BigDecimal waitRechargeAmt = BigDecimal.ZERO;
        // 本月待结算=本月已核销订单，需要补贴给商户的金额
        BigDecimal monthWaitSettleAmt = BigDecimal.ZERO;
        // 上月结算=上个自然月实际结算打款给商户的补贴金额
        BigDecimal lastMonthSettleAmt = BigDecimal.ZERO;


        LocalDate nowLocalDate = LocalDate.now();
        // 本月1号
        String firstDayOfMonthStr = LocalDateUtil.toLocalDateToString(nowLocalDate.with(TemporalAdjusters.firstDayOfMonth()), Constant.YYYY_MM_DD) + " 00:00:00";
        // 本月最后一天
        String lastDayOfMonthEndStr = LocalDateUtil.toLocalDateToString(nowLocalDate.with(TemporalAdjusters.lastDayOfMonth()), Constant.YYYY_MM_DD) + " 23:59:59";
        // 本月最后一天
        LocalDateTime firstDayOfMonthStart = LocalDateUtil.toLocalDateTime(firstDayOfMonthStr, Constant.YYYY_MM_DD_HH_MM_SS);
        LocalDateTime lastDayOfMonthEnd = LocalDateUtil.toLocalDateTime(lastDayOfMonthEndStr, Constant.YYYY_MM_DD_HH_MM_SS);

        // 查询待支付/支付失败的商品补贴的订单结算数据
        OrderSettleBillDto orderSettleBillDto = new OrderSettleBillDto();
        orderSettleBillDto.setBusinessId(businessId);
        orderSettleBillDto.setTradeType(OrderSettleBillTradeTypeEnum.SUBSIDY_AMT.getValue());
        orderSettleBillDto.setTradeStates(Arrays.asList(OrderSettleBillTradeStateEnum.WAIT.getValue(), OrderSettleBillTradeStateEnum.FAIL.getValue()));
        List<OrderSettleBillVo> orderSettleBillVos = orderSettleBillApi.listByDto(orderSettleBillDto).unpack();
        if (!CollectionUtils.isEmpty(orderSettleBillVos)) {
            for (OrderSettleBillVo orderSettleBillVo : orderSettleBillVos) {
                LocalDateTime tradeTime = orderSettleBillVo.getTradeTime();
                if (tradeTime.compareTo(firstDayOfMonthStart) >= 0 && tradeTime.compareTo(lastDayOfMonthEnd) <= 0) {
                    monthWaitSettleAmt = monthWaitSettleAmt.add(orderSettleBillVo.getTradeAmt());
                }
                waitRechargeAmt = waitRechargeAmt.add(orderSettleBillVo.getTradeAmt());
            }
        }

        // 根据商家id查询已结算待打款(已核销)的的订单,累加总补贴金额
        OrderDto orderDto = new OrderDto();
        orderDto.setBusinessId(businessId);
        orderDto.setOrderStates(Collections.singletonList(OrderStateEnum.VERIFIED.getValue()));
        List<OrderVo> orderVos = orderApi.listByDto(orderDto).unpack();
        if (!CollectionUtils.isEmpty(orderVos)) {
            List<Long> orderIds = orderVos.stream().map(OrderVo::getId).collect(Collectors.toList());
            OrderItemDto orderItemDto = new OrderItemDto();
            orderItemDto.setOrderIds(orderIds);
            orderItemDto.setSubOrderStates(Collections.singletonList(SubOrderStateEnum.VERIFIED.getValue()));
            orderItemDto.setStartVerifyTime(firstDayOfMonthStr);
            orderItemDto.setEndVerifyTime(lastDayOfMonthEndStr);
            List<OrderItemVo> orderItemVos = orderItemApi.listByDto(orderItemDto).unpack();
            if (!CollectionUtils.isEmpty(orderItemVos)) {
                for (OrderItemVo orderItemVo : orderItemVos) {
                    monthWaitSettleAmt = monthWaitSettleAmt.add(orderItemVo.getTotalSubsidyAmt());
                }
            }
        }

        // 根据商家id+上月查询实际结算的补贴金额
        LocalDate lastMonthLocalDate = nowLocalDate.plusMonths(-1);
        // 上月1号
        LocalDate firstDayOfLastMonth = lastMonthLocalDate.with(TemporalAdjusters.firstDayOfMonth());
        // 上月最后一天
        LocalDate lastDayOfLastMonth = lastMonthLocalDate.with(TemporalAdjusters.lastDayOfMonth());
        String firstDayOfLastMonthStartStr = LocalDateUtil.toLocalDateToString(firstDayOfLastMonth, Constant.YYYY_MM_DD) + " 00:00:00";
        String lastDayOfLastMonthEndStr = LocalDateUtil.toLocalDateToString(lastDayOfLastMonth, Constant.YYYY_MM_DD) + " 23:59:59";

        orderSettleBillDto = new OrderSettleBillDto();
        orderSettleBillDto.setBusinessId(businessId);
        orderSettleBillDto.setTradeType(OrderSettleBillTradeTypeEnum.SUBSIDY_AMT.getValue());
        orderSettleBillDto.setTradeState(OrderSettleBillTradeStateEnum.SUCCESS.getValue());
        orderSettleBillDto.setStartTradeTime(firstDayOfLastMonthStartStr);
        orderSettleBillDto.setEndTradeTime(lastDayOfLastMonthEndStr);
        orderSettleBillVos = orderSettleBillApi.listByDto(orderSettleBillDto).unpack();
        if (!CollectionUtils.isEmpty(orderSettleBillVos)) {
            for (OrderSettleBillVo orderSettleBillVo : orderSettleBillVos) {
                lastMonthSettleAmt = lastMonthSettleAmt.add(orderSettleBillVo.getTradeAmt());
            }
        }

        // 保留两位，舍去第三位
        BigDecimal feeAmt = waitRechargeAmt.multiply(Constant.BANK_PAY_FEE_AMT_RATE).setScale(2, BigDecimal.ROUND_DOWN);
        BigDecimal invoiceAmt = waitRechargeAmt.multiply(Constant.BANK_PAY_INVOICE_AMT_RATE).setScale(2, BigDecimal.ROUND_DOWN);
        waitRechargeAmt = waitRechargeAmt.add(feeAmt).add(invoiceAmt).setScale(2, BigDecimal.ROUND_DOWN);

        waitRechargeAmt = waitRechargeAmt.subtract(subsidyAmt).max(BigDecimal.ZERO);

        BusinessSubsidyVo businessSubsidyVo = new BusinessSubsidyVo();
        businessSubsidyVo.setSubsidyAmt(subsidyAmt);
        businessSubsidyVo.setWaitRechargeAmt(waitRechargeAmt);
        businessSubsidyVo.setMonthWaitSettleAmt(monthWaitSettleAmt);
        businessSubsidyVo.setLastMonthSettleAmt(lastMonthSettleAmt);

        return businessSubsidyVo;
    }

    public Result<List<SubsidyAmtBillVo>> listSubsidyAmtBill(SubsidyAmtBillDto subsidyAmtBillDto) {
        Long businessId = subsidyAmtBillDto.getBusinessId();
        if (businessId == null || businessId <= 0) {
            Long userId = subsidyAmtBillDto.getUserId();
            if (userId == null || userId <= 0) {
                Throw.isBusinessException(ResponseEnums.USER_ACCESS_DENIED);
            }

            // 根据userId查询商家id
            BusinessPageVo businessPageVo = businessApi.getByUserId(userId).unpack();
            if (businessPageVo == null) {
                Throw.isBusinessException(ResponseEnums.BUSINESS_ACCESS_DENIED);
            }

            businessId = businessPageVo.getId();
            subsidyAmtBillDto.setBusinessId(businessId);
        }

        LocalDateTime now = LocalDateTime.now();
        LocalDateTime startLocalDateTime = now.plusYears(-1);
        subsidyAmtBillDto.setStartLocalDateTime(LocalDateUtil.toLocalDateTimeToString(startLocalDateTime, Constant.YYYY_MM_DD_HH_MM_SS));

        // 查询用户最近一年的补贴金流水数据
        List<SubsidyAmtBillPageVo> subsidyAmtBillPageVos = subsidyAmtBillApi.listSubsidyAmtBill(subsidyAmtBillDto).unpack();
        if (CollectionUtils.isEmpty(subsidyAmtBillPageVos)) {
            return ResultGenerator.success();
        }

        Map<String, List<SubsidyAmtBillPageVo>> map = new HashMap<>();

        for (SubsidyAmtBillPageVo subsidyAmtBillPageVo : subsidyAmtBillPageVos) {
            LocalDateTime createTime = subsidyAmtBillPageVo.getCreateTime();
            String date = LocalDateUtil.toLocalDateToString(createTime.toLocalDate(), "yyyy-MM");

            List<SubsidyAmtBillPageVo> subsidyAmtBillPageVoList = new ArrayList<>();
            if (map.containsKey(date)) {
                subsidyAmtBillPageVoList = map.get(date);
            }

            subsidyAmtBillPageVoList.add(subsidyAmtBillPageVo);
            map.put(date, subsidyAmtBillPageVoList);
        }

        List<SubsidyAmtBillVo> commissionBillVos = new ArrayList<>();
        for (String date : map.keySet()) {
            List<SubsidyAmtBillPageVo> subsidyAmtBillPageVoList = map.get(date);

            BigDecimal monthIncome = BigDecimal.ZERO;
            BigDecimal monthExpend = BigDecimal.ZERO;
            for (SubsidyAmtBillPageVo commissionBillPageVo : subsidyAmtBillPageVoList) {
                BigDecimal tradeAmt = commissionBillPageVo.getTradeAmt();
                Integer getBillType = commissionBillPageVo.getBillType();
                if (BillTypeEnum.INCOME.getValue().equals(getBillType)) {
                    monthIncome = monthIncome.add(tradeAmt);
                } else if (BillTypeEnum.EXPEND.getValue().equals(getBillType)) {
                    monthExpend = monthExpend.add(tradeAmt);
                }
            }

            String[] splitDate = date.split("-");

            SubsidyAmtBillVo subsidyAmtBillVo = new SubsidyAmtBillVo();
            subsidyAmtBillVo.setYear(splitDate[0]);
            subsidyAmtBillVo.setMonth(splitDate[1]);
            subsidyAmtBillVo.setMonthIncome(monthIncome);
            subsidyAmtBillVo.setMonthExpend(monthExpend);
            subsidyAmtBillVo.setSubsidyBills(subsidyAmtBillPageVoList);
            commissionBillVos.add(subsidyAmtBillVo);
        }

        return ResultGenerator.success(commissionBillVos);
    }
}
